#ifndef MYMAP_H_
#define MYMAP_H_

#include <string>
#include <vector>
#include "SnakeSegment.h"
#include "game-printer.h"

#define MAP_X CONSOLE_X_RES
#define MAP_Y CONSOLE_Y_RES

/*#define MAP_X 10
#define MAP_Y 10 */

#define C_PLAYER(x) '0'+x

using namespace std;

class SnakePlayer;//for snakespointers


class MyMap
{
private:
	char map[MAP_X][MAP_Y];
	char last_state_map[MAP_X][MAP_Y];
	static const char * mapBeginnerString;
	
	static MyMap * instance;
	int mines_amount;
	int round_number;/* number of current round*/
	bool load_static_map;//true by default
private:
	int validateMapCoords(int x,int y);
	void cleanSnakeData();//erases snakes data
	MyMap(void);/* private constructor - do a singleton*/
public:
	static MyMap * instanceOf();
	static MyMap * getInstance();//wrapper for instanceOf
	std::string serialize();
	void deserializeFrom(std::string &param);
	void generateMap();
	//void fillRandomNumbers();
	void reset();//reset with empty points
	bool isCollisionAt(int x, int y);
	bool isAppleAt(int x, int y);
	bool isMineAt(int x, int y);
	bool isBonusAt(int x, int y);
	bool isStarAt(int x, int y);
	bool isEmptyAt(int x, int y);
	SnakePlayer * getSnakePlayerByNumber(int number);/**< returns snake player by number or NULL if not found */
	char getMapCharAt(int x, int y);
	char getMapCharIfChanged(int x,int y);/* returns field char or not_changed_state if nothing changed, map_error_char if coords not valid*/
	SnakeSegment * generateNextAppleOnMap();//return generated segment coords
	SnakeSegment * generateFieldForSnake();//return generated segment coords
	SnakeSegment getSegmentAtDirection(Direction d,int x,int y);
	Direction getOppositeDirectionFor(Direction d);/* gets oposite direction value to direction given as parameter*/
	void debugMap();
	void setMapCharAt(char c,int x,int y);
	void registerSnakePlayer(SnakePlayer *sp);
	void unregisterSnakePlayer(SnakePlayer *sp);
	bool checkBelongsToSnakes(int x,int y);//if segments belongs to some snake ->true
	void debugRegisteredPlayers();
	void printSnakesOnMap();
	void resetMapAndSnakes();
	void cleanupLastChanges();/* cleans last state of map (cleans changes list)*/
	void markAllChanged();
	void setRoundNumber(int number);
	int getRoundNumber();
	int incrementRoundNumber();//increments & returns new round number
	int getWinPlayerNumber();
	void markAsChanged(int x, int y);
	void setLoadStaticMap(bool param);//if true map won't be dinamically generated
public  :
	//constant chars which can be found on the map
	static const char apple;
	static const char level_entrance;
	static const char mine;
	static const char bonus_pill;
	static const char star;
	static const char empty_field;
	static const char declared_for_snake;
	/** values needed by renderer (prints only fields that changed its state) */
	static const char changed_state;/**<  jesli stan sie zmienil*/
	static const char not_changed_state;/** if state NOT changed*/
	static const char map_error_char;
	static const int snake_winner_none;
	static const int snake_winner_all_lost;
	bool serverMap;//if server map=1


private :
	vector<SnakePlayer *> snakesPlayers;
	int applesAmount;//give value in constructor
public  :
	~MyMap(void);
};

#endif /*MYMAP_H_*/
